package com.example.demo.dubbo.service;

import java.util.concurrent.TimeUnit;

import com.alibaba.dubbo.config.annotation.Service;
import com.example.demo.mapper.StudentMapper;
import com.example.dubbo.service.StudentService;
import com.example.model.Student;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@Service(interfaceClass = StudentService.class, version = "1.0.0", timeout = 35000)
public class StudentServiceImpl implements StudentService {

  @Autowired
  private StudentMapper studentMapper;

  @Autowired
  private RedisTemplate<Object, Object> redisTemplate;

  @Override
  public Student queryStudentById(Integer id) {
    return studentMapper.selectByPrimaryKey(id);
  }

  @Transactional
  @Override
  public int modifyStudentById(Student student) {
    int modifyCount = studentMapper.updateByPrimaryKeySelective(student);

    int a = 10 / 0;
    return modifyCount;
  }

  @Override
  public Long queryAllStudentCount() {

    // 设置 redisTemplate 对象 key 的序列化方式
    redisTemplate.setKeySerializer(new StringRedisSerializer());

    // 从 redis 缓存中获取总人数
    Long allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
    // // 判断是否为空
    // if (null == allStudentCount) {
    // System.out.println("从数据库查。。。。");
    // // 去数据库查询，并存放到 redis 缓存中
    // allStudentCount = studentMapper.selectAllStudentCount();
    // redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 15,
    // TimeUnit.SECONDS);
    // } else {
    // System.out.println("从redis查。。。");
    // }

    // 以上代码在多线程高并发的时候，会出现：缓存穿透
    // 通过双重检测+同步语句块来解决以上问题

    // 判断是否为空
    if (null == allStudentCount) {
      // 设置同步代码块
      synchronized (this) {

        // 再次从redis中获取学生总数
        allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
        // 再次判断是否为空
        if (null == allStudentCount) {
          System.out.println("从数据库查。。。。");
          allStudentCount = studentMapper.selectAllStudentCount();
          redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 15, TimeUnit.SECONDS);
        } else {
          System.out.println("从redis查。。。");
        }
      }
    } else {
      System.out.println("从redis查。。。");
    }
    return allStudentCount;
  }
}
